// Normally only called on the server.
XfMakeVehicleReserved= {
	private ["_vec","_access","_allowed_crew","_allowed_drivers","_allowed_gunners","_sides","_units","_side"];

	_vec = _this select 0;
	_allowed_crew = _this select 1;
	_allowed_drivers = _this select 2;
	_allowed_gunners = _this select 3;
	_sides = [];
	_units = [];
	{
		if (typename _x == typename west) then {
			_sides set [count _sides, _x];
		} else {
			_units set [count _units, _x];
		};
	} foreach _allowed_crew;
	_access = [];
	_access set [0, _sides];
	_access set [1, _units];
	_access set [2, _allowed_drivers];
	_access set [3, _allowed_gunners];
	_vec setVariable ["VehicleAccessArray",_access, true];
	_vec addEventHandler ["getin", XfCheckReservedVehicle];
	// diag_log Format["(%1)[%2]: %3: %4",diag_tickTime,"reservedvehicle.sqf","Reserved Vehicle", [_vec, typeof _vec, _access]];
};

// Called on all computers where an IA or player can mount a vehicle.
// You need to add a GetIn event on all computers for the given vehicle.
XfCheckReservedVehicle = {
	private ["_vec","_position","_unit","_access","_sides","_units","_drivers","_gunners","_allowed","_override","_idx"];
	_vec = (_this select 0);
	_position = (_this select 1);
	_unit = (_this select 2);
	// diag_log Format["(%1)[%2]: %3: %4",diag_tickTime,"reservedvehicle.sqf","XfCheckReservedVehicle", _this];
	// Checks needed only on the server
	if (X_Server) then {
		_allowed = false;
		_access = _vec getVariable "VehicleAccessArray";
		if (isnil "_access") exitWith { diag_log Format["(%1)[%2]: %3: %4",diag_tickTime,"reservedvehicle.sqf","No access configured", [_vec, typeof _vec]]; };
		if (typename _access != typename []) exitWith { diag_log Format["(%1)[%2]: %3: %4",diag_tickTime,"reservedvehicle.sqf","No access configured", [_vec, typeof _vec, _access]]; };
		if (count _access <= 0) exitWith { diag_log Format["(%1)[%2]: %3: %4",diag_tickTime,"reservedvehicle.sqf","No access configured", [_vec, typeof _vec, _access]]; };
		_sides = [];
		if (count _access > 0) then { _sides = _access select 0; };
		_units = [];
		if (count _access > 0) then { _units = _access select 1; };
		_drivers = [];
		if (count _access > 0) then { _drivers = _access select 2; };
		_gunners = [];
		if (count _access > 0) then { _gunners = _access select 3; };

		// We check that the unit is of allowed side
		if (!_allowed) then {
			_idx = _sides find (side _unit);
			_allowed = (_idx >= 0);
		};
		// We check by player slot
		if (!_allowed) then {
			_idx = _units find (str _unit);
			_allowed = (_idx >= 0);
		};
		// We check by player name
		if (!_allowed) then {
			_idx = _units find (name _unit);
			_allowed = (_idx >= 0);
		};
		// We check by player uid
		if (!_allowed) then {
			_idx = _units find (getPlayerUID _unit);
			_allowed = (_idx >= 0);
		};
		// if (_allowed) then {
			// diag_log Format["(%1)[%2]: %3: %4",diag_tickTime,"reservedvehicle.sqf","Allowed Before Positions", [_vec, typeof _vec, _unit, typeof _unit, str _unit, name _unit, getPlayerUID _unit]];
		// } else {
			// diag_log Format["(%1)[%2]: %3: %4",diag_tickTime,"reservedvehicle.sqf","Not Allowed Before Positions", [_vec, typeof _vec, _unit, typeof _unit, str _unit, name _unit, getPlayerUID _unit]];
		// };
		// We double check for the given position
		// positions: "driver", "gunner", "commander" or "cargo"
		switch (toupper(_position)) do {
			case "DRIVER": {
				if (count _drivers > 0) then {
					_idx = _drivers find (str _unit);
					if (_idx < 0) then { _idx = _drivers find (name _unit); };
					if (_idx < 0) then { _idx = _drivers find (getPlayerUID _unit); };
					if (_idx >= 0 && !_allowed) then { _allowed = true; };
					if (_idx < 0 && _allowed) then { _allowed = false; };
				};
			};
			case "GUNNER": {
				if (count _gunners > 0) then {
					_idx = _gunners find (str _unit);
					if (_idx < 0) then { _idx = _gunners find (name _unit); };
					if (_idx < 0) then { _idx = _gunners find (getPlayerUID _unit); };
					if (_idx >= 0 && !_allowed) then { _allowed = true; };
					if (_idx < 0 && _allowed) then { _allowed = false; };
				};
			};
			case "COMMANDER": {
				if (count _gunners > 0) then {
					_idx = _gunners find (str _unit);
					if (_idx < 0) then { _idx = _gunners find (name _unit); };
					if (_idx < 0) then { _idx = _gunners find (getPlayerUID _unit); };
					if (_idx >= 0 && !_allowed) then { _allowed = true; };
					if (_idx < 0 && _allowed) then { _allowed = false; };
				};
			};
			default{
				// Cargo, do nothing
			};
		};
		
		// We check that the unit is an AI and that it is part of the group of a player
		if (!_allowed && !isplayer _unit) then {
			_override = false;
			{ if (isplayer _x) then {
				_override = true;
				diag_log Format["(%1)[%2]: %3: %4",diag_tickTime,"reservedvehicle.sqf","AI With Player", [_vec, typeof _vec, _unit, typeof _unit, str _unit, name _x, getPlayerUID _x]];
			  };
			} foreach (units (group _unit));
			_allowed = _override;
		};

		if (!_allowed) then {
			_override = _unit getVariable "CanMountAllVehicles";
			if (!isnil "_override") then {
				diag_log Format["(%1)[%2]: %3: %4",diag_tickTime,"reservedvehicle.sqf","Unit with override", [_vec, typeof _vec, _unit, typeof _unit, str _unit, name _unit, getPlayerUID _unit]];
				_allowed = _override;
			};
		};
		
		if (!_allowed) then {
			["d_msg",["STR_DOM_RESERVEDVEHICLE","unit",_unit,"side"]] call XNetCallEvent;
			diag_log Format["(%1)[%2]: %3: %4",diag_tickTime,"reservedvehicle.sqf","Not Allowed", [_vec, typeof _vec, _unit, typeof _unit, str _unit, name _unit, getPlayerUID _unit]];
			_unit action ["getout",_vec];
			unassignVehicle _unit;
			_unit leaveVehicle _vec;
		} else {
			// diag_log Format["(%1)[%2]: %3: %4",diag_tickTime,"reservedvehicle.sqf","Allowed", [_vec, typeof _vec, _unit, typeof _unit, str _unit, name _unit, getPlayerUID _unit]];
			if (toupper(_position) != "CARGO") then {
				_allowed_msg = getText (missionConfigFile >> "mission_template" >> "team_config" >> "allowed_message");
				if (!isnil "_allowed_msg") then {
					if (_allowed_msg != "") then {
						["d_msg",[_allowed_msg,"unit",_unit,"group"]] call XNetCallEvent;
					};
				};
			};
		};
	} else {
		diag_log Format["(%1)[%2]: %3: %4",diag_tickTime,"reservedvehicle.sqf","Not on Server", [_vec, typeof _vec, _unit, typeof _unit, str _unit, name _unit, getPlayerUID _unit]];
	};
};